// import { Server } from 'socket.io'
import { SocketRoomEvent } from '../constant/SocketRoomEvent'
import Room from '../data/Room'
import { ISocketData } from '../data/SocketData'
import { User } from '../data/User'
import SocketManager from '../websocket/SocketManager'

/**
 * 房间管理类
 * 创建房间，并管理玩家加入未满的房间
 */
export default class RoomManager {
  private static _instance: RoomManager | null = null
  private _roomFullMap: Map<string, Room>       // 满人房间集合；key:房间id，value:房间对象
  private _roomNotFullMap: Map<string, Room>    // 未满房间集合；
  private _userOnRoomMap: Map<string, Room>     // 用户所在房间，用于防止重复进入多个房间

  public static get instance() {
    if (this._instance == null) {
      this._instance = new RoomManager()
    }
    return this._instance
  }

  private constructor() {
    this._roomFullMap = new Map()
    this._roomNotFullMap = new Map()
    this._userOnRoomMap = new Map()
  }

  /**
   * 加入一个未满的房间
   * @param uid 
   */
  public intoRoom(user: User): { room: Room, index: number } {
    let room: Room | undefined

    // 如果用户已经在某个房间了，那么直接返回
    // TODO: 重连处理
    // if (this._userOnRoomMap.has(user.id)) {
    //   // 进入此处，说明用户重新连接
    //   
    //   room = this._userOnRoomMap.get(user.id)

    //   if (room == undefined) {
    //     throw new Error(`[room] room = undefined`)
    //   }

    //   return room
    // }

    // 找到一个没满人的房间
    if (this._roomNotFullMap.size == 0) {
      // 没有房间，创建新房间
      room = new Room(3)
    } else {
      // 获取一个未满房间
      room = this._roomNotFullMap.values().next().value
    }

    // 无法创建房间
    if (room == undefined) {
      throw new Error(`[room] unable to create room, room = undefined`)
    }

    // 用户加入房间
    const playerIndex = room.intoRoom(user)
    this._userOnRoomMap.set(user.id, room)    // 记录用户所在房间
    console.log(`[room] ${user.id} into room`)

    // 若房间已满，加入到已满房间Map中
    if (room.isFull()) {
      this._roomFullMap.set(room.id, room)
      this._roomNotFullMap.delete(room.id)
    } else if (room?.isFull() == false) {
      this._roomNotFullMap.set(room.id, room)
      this._roomFullMap.delete(room.id)
    }

    return { room, index: playerIndex }
  }

  /**
   * 离开房间
   */
  public leaveRoom(roomId: string, uid: string): number {
    // 找到房间
    let room: Room | undefined = this._roomFullMap.get(roomId) || this._roomNotFullMap.get(roomId)
    if (room == undefined) {
      throw new Error('[room] This room does not exist, room = undefined')
    }

    // 离开房间
    const index = room.leaveRoom(uid)
    this._userOnRoomMap.delete(uid)

    // TODO: 房间状态不为空闲，那么为用户掉线，不应该移出用户数据
    // TODO: 用户掉线并且游戏结算后，自动离开房间（防止占用资源）

    // 判断是否房间已满
    if (room.isFull()) {
      this._roomFullMap.set(room.id, room)
      this._roomNotFullMap.delete(room.id)
    } else if (room.isFull() == false) {
      this._roomNotFullMap.set(room.id, room)
      this._roomFullMap.delete(room.id)
    }

    // 房间为空时，删除房间对象
    if (room.isEmpty()) {
      this._roomFullMap.delete(room.id)
      this._roomNotFullMap.delete(room.id)
    }

    return index
  }

  /**
   * 获得房间对象
   * @param roomId 
   */
  public getRoomByRoomId(roomId: string): Room {
    const room = this._roomFullMap.get(roomId) || this._roomNotFullMap.get(roomId)
    if (room == undefined) {
      throw new Error(`[room] room does not exist, room id = ${roomId}`)
    }
    return room
  }

  /**
   * 获得用户所在的房间对象
   * @param uid 
   */
  public getRoomByUserId(uid: string): Room {
    const room = this._userOnRoomMap.get(uid)
    if (room == undefined) {
      throw new Error(`[room] The user is not in the room, user id = ${uid}`)
    }
    return room
  }

  // /**
  //  * 给房间人发数据
  //  * @param roomId 
  //  * @param socketData 
  //  * @param unlessUserId  设置不发的用户
  //  */
  // private emit(roomId: string, socketData: ISocketData, unlessUserId?: string) {
  //   if (unlessUserId) {
  //     const socket = SocketManager.instance.getClientSocket(unlessUserId)
  //     if (socket === undefined) {
  //       throw new Error(`uid=${unlessUserId} socket not connected`)
  //     }
  //     socket.to(roomId).emit(socketData.event, socketData)
  //   } else {
  //     SocketManager.instance.io.to('roomId').emit(socketData.event, socketData)
  //   }
  // }
}